/*实现异步日志缓冲区*/
#ifndef _MY_BUFFER_H_
#define _MY_BUFFER_H_

#include "util.hpp"
#include <vector>
#include <cassert>

namespace ltylog
{
    #define DEFAULT_BUFFER_SIZE (1*1024*1024)
    #define THRESHOLD_BUFFER_SIZE (8*1024*1024)
    #define INCREMENT_BUFFER_SIZE (1*1024*1024)
    class Buffer
    {
    public:
        Buffer():_buffer(DEFAULT_BUFFER_SIZE),_reader_idx(0),_writer_idx(0){};
        //向缓冲区写入数据
        void push(const char* data,size_t len)
        {
            //空间不够-扩容
            ensureEnoughSize(len);
            //拷贝数据到缓冲区
            std::copy(data,data+len,&_buffer[_writer_idx]);
            //写入位置后移
            moveWriter(len);
        }
        
        //返回可读数据的起始地址
        const char* begin()
        {
            return &_buffer[_reader_idx];
        }
        //返回可读写数据长度
        size_t writeAbleSize()
        {
            //扩容不存在可写空间大小，总是可写
            //这个接口仅针对固定大小缓冲区提供
            return (_buffer.size() - _writer_idx);
        }
        size_t readAbleSize()
        {
            //双缓冲区处理完就交换，不存在空间循环使用
            return (_writer_idx - _reader_idx);
        }
        //读写指针偏移操作
        void moveReader(size_t len)
        {
            assert(len<=readAbleSize());
            _reader_idx += len;
        }
        //重置读写位置，初始化缓冲区
        void reset()
        {
            _writer_idx=0;
            _reader_idx=0;
        }
        //缓冲区交换操作
        void swap(Buffer &buffer)
        {
            _buffer.swap(buffer._buffer);
            std::swap(_reader_idx,buffer._reader_idx);
            std::swap(_writer_idx,buffer._writer_idx);
        }
        //判断缓冲区是否为空
        bool empty()
        {
            return (_reader_idx == _writer_idx);
        }
    private:
        //对空间进行扩容
        void ensureEnoughSize(size_t len)
        {
            if(len <= writeAbleSize()) return ;//不需要扩容
            size_t new_size=0;
            if(_buffer.size()<THRESHOLD_BUFFER_SIZE)
            {
                new_size=_buffer.size()*2 + len;//小于阈值翻倍增长
            }
            else
            {
                new_size=_buffer.size()+INCREMENT_BUFFER_SIZE + len;//线性增长
            }
            _buffer.resize(new_size);
        }
        //读写指针偏移操作
        void moveWriter(size_t len)
        {
            assert(len<=_buffer.size());
            _writer_idx += len;
        }
    private:
        std::vector<char> _buffer;
        size_t _reader_idx;//当前可读数据的指针
        size_t _writer_idx;//当前可写数据的指针
    };
}

#endif